package com.cb2.algorithm.leetcode;

/**
 * <a href='https://leetcode.cn/problems/double-a-number-represented-as-a-linked-list'>翻倍以链表形式表示的数字(Double a Number Represented as a Linked List)</a>
 * <p>给你一个 非空 链表的头节点 head ，表示一个不含前导零的非负数整数。</p>
 * <p>将链表 翻倍 后，返回头节点 head 。</p>
 *
 * <p>
 * <b>示例：</b>
 * <pre>
 * 示例 1：
 *      输入：head = [1,8,9]
 *      输出：[3,7,8]
 *      解释：上图中给出的链表，表示数字 189 。返回的链表表示数字 189 * 2 = 378 。
 *
 * 示例 2：
 *      输入：head = [9,9,9]
 *      输出：[1,9,9,8]
 *      解释：上图中给出的链表，表示数字 999 。返回的链表表示数字 999 * 2 = 1998 。
 * </pre>
 * </p>
 *
 * <p>
 * <b>提示：</b>
 *  <ul>
 *     <li>链表中节点的数目在范围 [1, 10^4] 内</li>
 *     <li>0 <= Node.val <= 9</li>
 *     <li>生成的输入满足：链表表示一个不含前导零的数字，除了数字 0 本身。</li>
 *  </ul>
 * </p>
 *
 * @author c2b
 * @since 2023/12/12 14:28
 */
public class LC2816DoubleNumberRepresentedAsLinkedList_M {

    static class Solution {
        public ListNode doubleIt(ListNode head) {
            ListNode dummyHead = new ListNode(0, head);
            // 当前节点的值，由下一个节点的值与当前节点的值共同决定
            // 下一个节点最大值为9，翻倍后为18，后续节点如果有进位，值最大为19，进位为1。不会出现大于1的情况
            for (ListNode currNode = dummyHead; currNode.next != null; currNode = currNode.next) {
                // 将next节点值翻倍
                currNode.next.val *= 2;
                // 将进位加到当前节点值
                currNode.val += currNode.next.val / 10;
                // 将next只保留个位数
                currNode.next.val %= 10;
            }
            //ListNode currNode = dummyHead;
            //while (currNode.next != null) {
            //    // 将next节点值翻倍
            //    currNode.next.val *= 2;
            //    // 将进位加到当前节点值
            //    currNode.val += currNode.next.val / 10;
            //    // 将next只保留个位数
            //    currNode.next.val %= 10;
            //    // 下一个节点
            //    currNode = currNode.next;
            //}
            return dummyHead.val > 0 ? dummyHead : dummyHead.next;
        }


        public ListNode doubleIt2(ListNode head) {
            head = reserve(head);
            int carry = 0;
            ListNode dummyHead = new ListNode(-1);
            ListNode currNode = dummyHead;
            while (head != null || carry != 0) {
                if (head != null) {
                    carry += head.val * 2;
                    head = head.next;
                }
                currNode.next = new ListNode(carry % 10);
                carry /= 10;
                currNode = currNode.next;
            }
            return reserve(dummyHead.next);
        }

        private ListNode reserve(ListNode head) {
            ListNode prevNode = null;
            ListNode currNode = head;
            ListNode nextNode;
            while (currNode != null) {
                nextNode = currNode.next;
                currNode.next = prevNode;
                prevNode = currNode;
                currNode = nextNode;
            }
            return prevNode;
        }
    }

    public static void main(String[] args) {
        Solution solution = new Solution();
        Printer.printListNode(solution.doubleIt(Generator.create(1, 8, 9)));
        Printer.printListNode(solution.doubleIt(Generator.create(9, 9, 9)));
        Printer.printListNode(solution.doubleIt2(Generator.create(1, 8, 9)));
        Printer.printListNode(solution.doubleIt2(Generator.create(9, 9, 9)));
    }
}